package com.dhq.myapp.base.divider

import android.graphics.Canvas
import android.graphics.Rect
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.view.View
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView

/**
 * DESC RecyclerViewDivider工具类
 * Created by admin on 2017/11/17.
 */
class GridDivider(builder: Builder) : DividerFactory() {

    private val bounds = Rect()
    private val divider: Drawable?
    private val columnSpace: Int
    private val rowSpace: Int
    private val hideRoundDivider: Boolean
    private var spanCount = 1
    private var itemWidth: Int = 0
    private var itemHeight: Int = 0

    init {
        this.divider = builder.drawable
        this.columnSpace = builder.columnSpace
        this.rowSpace = builder.rowSpace
        this.hideRoundDivider = builder.hideLastDivider
    }

    override fun drawDivider(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        if (parent.layoutManager == null || divider == null) {
            return
        }
        val layoutManager = parent.layoutManager

        // 判断是否是GridLayoutManager
        if (layoutManager is GridLayoutManager) {
            // 获取列数
            spanCount = layoutManager.spanCount
            drawSpace(c, parent)
        }
    }

    override fun calculateItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
        val layoutManager = parent.layoutManager as? GridLayoutManager ?: return
        spanCount = layoutManager.spanCount

        val position = parent.getChildAdapterPosition(view)
        val column = position % spanCount // item column

        if (hideRoundDivider) {
            outRect.left = column * columnSpace / spanCount // column * ((1f / spanCount) * spacing)
            outRect.right = columnSpace - (column + 1) * columnSpace / spanCount // spacing - (column + 1) * ((1f / spanCount) * spacing)
            if (position >= spanCount) {
                outRect.top = columnSpace // item top
            }
        } else {
            outRect.left = columnSpace - column * columnSpace / spanCount // spacing - column * ((1f / spanCount) * spacing)
            outRect.right = (column + 1) * columnSpace / spanCount // (column + 1) * ((1f / spanCount) * spacing)

            if (position < spanCount) { // top edge
                outRect.top = columnSpace
            }
            outRect.bottom = columnSpace // item bottom
        }
    }

    private fun drawSpace(canvas: Canvas, parent: RecyclerView) {
        drawSpaceTest(canvas, parent)
    }

    private fun drawSpaceTest(canvas: Canvas, parent: RecyclerView) {
        canvas.save()
        val layoutManager = parent.layoutManager as? GridLayoutManager ?: return
        spanCount = layoutManager.spanCount
        val childCount = parent.childCount
        var left: Float
        var top: Float
        var right: Float
        var bottom: Float

        val rowNum = (childCount - 1) / spanCount + 1
        val parentWidth = parent.measuredWidth - parent.paddingLeft - parent.paddingRight
        val parentHeight = parent.measuredHeight - parent.paddingTop - parent.paddingBottom
        val lastSpan = childCount % spanCount

        if (!hideRoundDivider) {
            // 绘制行
            for (i in 0..rowNum) {
                val drawable = getDivider() ?: continue

                if (i == rowNum) {
                    val dividerCenter = parent.paddingTop + parentHeight / rowNum * i
                    top = dividerCenter - columnSpace / 2f
                    left = parent.paddingLeft.toFloat()
                    val lastRowdividerWidth = if (lastSpan == 0) {
                        parent.right - parent.paddingRight.toFloat()
                    } else {
                        parent.paddingLeft + parentWidth / spanCount * lastSpan.toFloat()
                    }
                    right = lastRowdividerWidth
                    bottom = dividerCenter + columnSpace / 2f
                    drawable.setBounds(left.toInt(), top.toInt(), right.toInt(), bottom.toInt())
                } else {
                    val dividerCenter = parent.paddingTop + parentHeight / rowNum * i
                    if (rowNum == 1 && i == 0) {
                        top = dividerCenter - columnSpace / 2f
                        left = parent.paddingLeft.toFloat()
                        val lastRowdividerWidth = if (lastSpan == 0) {
                            parent.right - parent.paddingRight.toFloat()
                        } else {
                            parent.paddingLeft + parentWidth / spanCount * lastSpan.toFloat()
                        }
                        right = lastRowdividerWidth
                        bottom = dividerCenter + columnSpace / 2f
                        drawable.setBounds(left.toInt(), top.toInt(), right.toInt(), bottom.toInt())
                    } else {
                        top = dividerCenter - columnSpace / 2f
                        left = parent.paddingLeft.toFloat()
                        right = parent.right - parent.paddingRight.toFloat()
                        bottom = dividerCenter + columnSpace / 2f
                        drawable.setBounds(left.toInt(), top.toInt(), right.toInt(), bottom.toInt())
                    }
                }
                drawable.draw(canvas)
            }
        } else {
            for (i in 1 until rowNum) {
                val dividerCenter = parent.paddingTop + parentHeight / rowNum * i
                top = dividerCenter - columnSpace / 2f
                left = parent.paddingLeft.toFloat()
                right = parent.right - parent.paddingRight.toFloat()
                bottom = dividerCenter + columnSpace / 2f
                val drawable = getDivider() ?: continue
                drawable.setBounds(left.toInt(), top.toInt(), right.toInt(), bottom.toInt())
                drawable.draw(canvas)
            }
        }

        if (!hideRoundDivider) {
            // 绘制列
            var columns = spanCount
            if (rowNum == 1 && lastSpan > 0) {
                columns = lastSpan
            }
            for (i in 0..columns) {
                val dividerCenter = parent.paddingLeft + parentWidth / spanCount * i
                top = parent.paddingTop.toFloat()
                left = dividerCenter - columnSpace / 2f
                right = dividerCenter + columnSpace / 2f
                bottom = if (rowNum > 1 && i > lastSpan) {
                    parent.getChildAt(childCount - 1).top.toFloat()
                } else {
                    parent.bottom - parent.paddingBottom.toFloat()
                }

                val drawable = getDivider() ?: continue
                drawable.setBounds(left.toInt(), top.toInt(), right.toInt(), bottom.toInt())
                drawable.draw(canvas)
            }
        } else {
            for (i in 1 until spanCount) {
                val dividerCenter = parent.paddingLeft + parentWidth / spanCount * i
                top = parent.paddingTop.toFloat()
                left = dividerCenter - columnSpace / 2f
                right = dividerCenter + columnSpace / 2f
                bottom = parent.bottom - parent.paddingBottom.toFloat()

                val drawable = getDivider() ?: continue
                drawable.setBounds(left.toInt(), top.toInt(), right.toInt(), bottom.toInt())
                drawable.draw(canvas)
            }
        }

        canvas.restore()
    }

    private fun getAdapterPosition(view: View): Int {
        return (view.layoutParams as RecyclerView.LayoutParams).viewAdapterPosition
    }

    private fun getDivider(): Drawable? {
        return divider
    }

    private fun getLeftSpaceWidth(position: Int): Int {
        return if (position % spanCount == 0) {
            getEdgeWidth()
        } else {
            getColumnSpace() / 2
        }
    }

    private fun getTopSpaceWidth(position: Int): Int {
        return if (position < spanCount) {
            getEdgeHeight()
        } else {
            getRowSpace() / 2
        }
    }

    private fun getRightSpaceWidth(position: Int): Int {
        return if (position % spanCount == spanCount - 1) {
            getEdgeWidth()
        } else {
            getColumnSpace() / 2
        }
    }

    private fun getBottomSpaceWidth(totalCount: Int, position: Int): Int {
        val totalRow = (totalCount - 1) / spanCount + 1
        val currentRow = position / spanCount + 1
        return if (totalRow == currentRow) {
            getEdgeWidth()
        } else {
            getRowSpace() / 2
        }
    }

    /**
     * 获取分割线宽度
     */
    private fun getColumnSpace(): Int {
        return if (divider is ColorDrawable) {
            columnSpace
        } else {
            divider?.intrinsicWidth ?: 0
        }
    }

    /**
     * 获取分割线高度
     */
    private fun getRowSpace(): Int {
        return if (divider is ColorDrawable) {
            rowSpace
        } else {
            divider?.intrinsicHeight ?: 0
        }
    }

    /**
     * 获取边缘分割线宽度
     */
    private fun getEdgeWidth(): Int {
        return if (hideRoundDivider) {
            0
        } else {
            getColumnSpace()
        }
    }

    /**
     * 获取边缘分割线高度
     */
    private fun getEdgeHeight(): Int {
        return if (hideRoundDivider) {
            0
        } else {
            getRowSpace()
        }
    }
}